home *** CD-ROM | disk | FTP | other *** search
- /* this file is a part of amp software, (C) tomislav uzelac 1996,1997
- */
-
- /* audio.c main amp source file
- *
- * Created by: tomislav uzelac Apr 1996
- * Karl Anders Oygard added the IRIX code, 10 Mar 1997.
- * Ilkka Karvinen fixed /dev/dsp initialization, 11 Mar 1997.
- * Lutz Vieweg added the HP/UX code, 14 Mar 1997.
- * Dan Nelson added FreeBSD modifications, 23 Mar 1997.
- * Andrew Richards complete reorganisation, new features, 25 Mar 1997
- * Edouard Lafargue added sajber jukebox support, 12 May 1997
- */
-
-
- #include "amp.h"
-
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #ifndef __BEOS__
- #include <sys/uio.h>
- #endif
-
- #include <sys/socket.h>
- #include <errno.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
-
- #define AUDIO
- #include "audio.h"
- #include "formats.h"
- #include "getbits.h"
- #include "huffman.h"
- #include "layer2.h"
- #include "layer3.h"
- #include "position.h"
- #include "rtbuf.h"
- #include "transform.h"
- #include "controldata.h"
- #include "guicontrol.h"
-
- #ifndef __BEOS__
- typedef int bool;
- #endif
-
- void statusDisplay(struct AUDIO_HEADER *header, int frameNo)
- {
- int minutes,seconds;
-
- if ((A_SHOW_CNT || A_SHOW_TIME) && !(frameNo%10))
- msg("\r");
- if (A_SHOW_CNT && !(frameNo%10) ) {
- msg("{ %d } ",frameNo);
- }
- if (A_SHOW_TIME && !(frameNo%10)) {
- seconds=frameNo*1152/t_sampling_frequency[header->ID][header->sampling_frequency];
- minutes=seconds/60;
- seconds=seconds % 60;
- msg("[%d:%02d]",minutes,seconds);
- }
- if (A_SHOW_CNT || A_SHOW_TIME)
- fflush(stderr);
- }
-
- int decodeMPEG(void)
- {
- struct AUDIO_HEADER header;
- int cnt,g,snd_eof;
- uid_t my_uid = getuid();
-
- #ifdef LINUX_REALTIME
- set_realtime_priority();
-
- setreuid(my_uid, my_uid);
-
- prefetch_initial_fill();
- #endif /* LINUX_REALTIME */
-
- initialise_globals();
-
- #ifndef LINUX_REALTIME
- if (A_FORMAT_WAVE) wav_begin();
- #endif /* LINUX_REALTIME */
-
- if ((g=gethdr(&header))!=0) {
- report_header_error(g);
- return -1;
- }
-
- if (header.protection_bit==0) getcrc();
-
- #ifdef LINUX_REALTIME
- if (setup_fancy_audio(&header)!=0) {
- warn("Cannot set up direct-to-DMA audio. Exiting\n");
- return -1;
- }
- #else
- if (setup_audio(&header)!=0) {
- warn("Cannot set up audio. Exiting\n");
- return -1;
- }
- #endif /* LINUX_REALTIME */
-
-
- show_header(&header);
-
- if (header.layer==1) {
- if (layer3_frame(&header,cnt)) {
- warn(" error. blip.\n");
- return -1;
- }
- } else if (header.layer==2)
- if (layer2_frame(&header,cnt)) {
- warn(" error. blip.\n");
- return -1;
- }
-
- #ifdef LINUX_REALTIME
- if (start_fancy_audio(&header)!=0) {
- warn("Cannot start direct-to-DMA audio. Exiting\n");
- return -1;
- }
- #endif /* LINUX_REALTIME */
-
-
- /*
- * decoder loop **********************************
- */
- snd_eof=0;
- cnt=0;
- while (!snd_eof) {
- while (!snd_eof && ready_audio()) {
- if ((g=gethdr(&header))!=0) {
- report_header_error(g);
- #ifdef LINUX_REALTIME
- cleanup_fancy_audio();
- #else
- if (g==GETHDR_EOF && A_FORMAT_WAVE) wav_end(&header);
- #endif /* LINUX_REALTIME */
- snd_eof=1;
- break;
- }
-
- if (header.protection_bit==0) getcrc();
-
- statusDisplay(&header,cnt);
-
- if (header.layer==1) {
- if (layer3_frame(&header,cnt)) {
- warn(" error. blip.\n");
- return -1;
- }
- } else if (header.layer==2)
- if (layer2_frame(&header,cnt)) {
- warn(" error. blip.\n");
- return -1;
- }
- cnt++;
- }
- #ifdef LINUX_REALTIME
- if (block_fancy_audio(snd_eof)!=0) {
- warn("Problems with direct-to-DMA audio\n");
- return -1;
- }
- #endif
- }
- #ifdef LINUX_REALTIME
- if (stop_fancy_audio()!=0) {
- warn("Cannot stop direct-to-DMA audio. Exiting\n");
- return -1;
- }
- #endif
- return 0;
- }
-
- int main(int argc,char **argv)
- {
- int argPos;
-
- argPos=args(argc,argv); /* process command line arguments */
-
- initialise_decoder(); /* initialise decoder */
-
- if (argc == 1) { /* Start amp as a GUI backend. */
- A_QUIET = TRUE; /* TODO: change this to A_GUI_CONTROLLED */
- #ifndef OS_SunOS
- gui_control();
- #endif
- } else {
- if (A_AUDIO_PLAY) { /* play each specified file */
- if (argPos<argc)
- for(;argPos<argc;argPos++) {
- #ifdef LINUX_REALTIME
- if (geteuid() != 0)
- die("effective UID not root, cannot use realtime buffering\n");
- rt_play(argv[argPos]);
- #else /* LINUX_REALTIME */
- play(argv[argPos],0);
- #endif /* LINUX_REALTIME */
- }
- else
- displayUsage();
- } else { /* convert the file to some format */
- if ((argPos+2)==argc)
- play(argv[argPos],argv[argPos+1]);
- else {
- warn("Invalid number of parameters\n");
- displayUsage();
- die("");
- }
- }
-
- msg("\nThank you for using amp!\n");
- exit(0);
- }
- exit(0);
- }
-
- /* call this once at the beginning
- */
- void initialise_decoder(void)
- {
- premultiply();
- imdct_init();
- calculate_t43();
- }
-
- /* call this before each file is played
- */
- void initialise_globals(void)
- {
- append=data=nch=0;
- f_bdirty=TRUE;
- bclean_bytes=0;
-
- memset(s,0,sizeof s);
- memset(res,0,sizeof res);
- }
-
- void report_header_error(int err)
- {
- switch (err) {
- case GETHDR_ERR: die("error reading mpeg bitstream. exiting.\n");
- break;
- case GETHDR_NS : warn("this is a file in MPEG 2.5 format, which is not defined\n");
- warn("by ISO/MPEG. It is \"a special Fraunhofer format\".\n");
- warn("amp does not support this format. sorry.\n");
- break;
- case GETHDR_FL1: warn("ISO/MPEG layer 1 is not supported by amp (yet).\n");
- break;
- case GETHDR_FF : warn("free format bitstreams are not supported. sorry.\n");
- break;
- case GETHDR_SYN: warn("oops, we're out of sync.\n");
- break;
- case GETHDR_EOF:
- default: ; /* some stupid compilers need the semicolon */
- }
- }
-
- /* TODO: there must be a check here to see if the audio device has been opened
- * successfuly. This is a bitch because it requires all 6 or 7 OS-specific functions
- * to be changed. Is anyone willing to do this at all???
- */
- int setup_audio(struct AUDIO_HEADER *header)
- {
- if (A_AUDIO_PLAY)
- if (AUDIO_BUFFER_SIZE==0)
- audioOpen(t_sampling_frequency[header->ID][header->sampling_frequency],
- (header->mode!=3 && !A_DOWNMIX),A_SET_VOLUME);
- else
- audioBufferOpen(t_sampling_frequency[header->ID][header->sampling_frequency],
- (header->mode!=3 && !A_DOWNMIX),A_SET_VOLUME);
- return 0;
- }
-
- void close_audio(void)
- {
- if (A_AUDIO_PLAY)
- if (AUDIO_BUFFER_SIZE!=0)
- audioBufferClose();
- else
- audioClose();
- }
-
- int ready_audio(void)
- {
- #ifdef LINUX_REALTIME
- return ready_fancy_audio();
- #else
- return 1;
- #endif
- }
-
- /* TODO: add some kind of error reporting here
- */
- void play(char *inFileStr, char *outFileStr)
- {
- if (strcmp(inFileStr,"-")==0)
- in_file=stdin;
- else {
- if ((in_file=fopen(inFileStr,"r"))==NULL) {
- warn("Could not open file: %s\n",inFileStr);
- return;
- }
- }
- if (outFileStr) {
- if (strcmp(outFileStr,"-")==0)
- out_file=stdout;
- else
- if ((out_file=fopen(outFileStr,"w"))==NULL) {
- warn("Could not write to file: %s\n",outFileStr);
- return;
- }
- msg("Converting: %s\n",inFileStr);
- }
-
- if (A_AUDIO_PLAY)
- msg("Playing: %s\n",inFileStr);
-
- /*
- *
- */
-
- decodeMPEG();
-
- close_audio();
- fclose(in_file);
- if (!A_AUDIO_PLAY) fclose(out_file);
- msg("\n");
- }
-
-